﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phuse.Net
{
    using System;
    using System.ServiceModel;
    using System.Text;
    using System.Threading.Tasks;

    using Phuse.Net.FakeReference;

    /// <summary>Implements a fake server that sends predetermined responses upon receiving expected commands.</summary>
    internal sealed class FakeServer : IDisposable
    {
        private FakeServerClient client = new FakeServerClient(
            new BasicHttpBinding(), new EndpointAddress("http://thunderbolt:42042/PhuseFakeServer"));

        private readonly Encoding encoding;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>Terminates the server.</summary>
        public void Dispose()
        {
            try
            {
                if (this.client != null)
                {
                    var clientInterface = (IFakeServer)this.client;

                    using (var task = Task.Factory.FromAsync(
                        clientInterface.BeginStop(null, null), clientInterface.EndStop))
                    {
                        task.Wait();
                    }

                    ((ICommunicationObject)this.client).Close();
                }
            }
            finally
            {
                this.client = null;
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal FakeServer(Encoding encoding, int port, byte[] greeting, bool disconnectAfterGreeting)
        {
            this.encoding = encoding;
            var clientInterface = (IFakeServer)this.client;

            using (var task = Task.Factory.FromAsync(
                clientInterface.BeginStart(port, greeting, disconnectAfterGreeting, null, null),
                clientInterface.EndStart))
            {
                task.Wait();
            }
        }

        internal void QueueCommand(byte[] expectedCommand, byte[] response)
        {
            if (this.client == null)
            {
                throw new ObjectDisposedException(this.ToString());
            }

            var clientInterface = (IFakeServer)this.client;

            using (var task = Task.Factory.FromAsync(
                clientInterface.BeginQueueCommand(expectedCommand, response, null, null),
                clientInterface.EndQueueCommand))
            {
                task.Wait();
            }
        }

        internal void QueueCommand(string expectedCommand, string response)
        {
            this.QueueCommand(this.encoding.GetBytes(expectedCommand), this.encoding.GetBytes(response));
        }
    }
}
